package com.dianxin.smartpark.service.attendance.impl;

import cn.hutool.core.date.DateUtil;
import com.chinatelecom.response.common.CommonResponseBody;
import com.chinatelecom.response.constant.ErrMsgEnum;
import com.chinatelecom.response.utils.BeanUtil;
import com.chinatelecom.response.utils.ResponseBodyWrapperUtil;
import com.dianxin.acl.api.acl.AclUserRpcService;
import com.dianxin.acl.api.dto.SsoDeptDTO;
import com.dianxin.acl.api.dto.SsoUserDTO;
import com.dianxin.acl.api.qo.SsoUserRpcQO;
import com.dianxin.smartpark.dao.dataobject.access.*;
import com.dianxin.smartpark.dao.dataobject.attendance.*;
import com.dianxin.smartpark.dao.mapper.access.SmartParkAccessControlPassRecordMapper;
import com.dianxin.smartpark.dao.mapper.attendance.*;
import com.dianxin.smartpark.dao.qo.access.SmartParkAccessControlPassRecordQO;
import com.dianxin.smartpark.dao.qo.attendance.SmartParkAttendanceRecordQO;
import com.dianxin.smartpark.dao.qo.attendance.SmartParkHolidayDetailQO;
import com.dianxin.smartpark.service.attendance.SmartParkAttendanceRecordService;
import com.dianxin.smartpark.service.attendance.SmartParkHolidayDetailService;
import com.dianxin.smartpark.service.utils.DateTimeUtil;
import com.dianxin.smartpark.service.vo.attendance.SmartParkAttendanceRecordVO;
import com.dianxin.sso.client.context.UserHolderContext;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @program: smart-park
 * @description: 考勤记录
 * @author: chenyong
 * @create: 2021-08-03 15:55
 */
@Service
public class SmartParkAttendanceRecordServiceImpl implements SmartParkAttendanceRecordService {
    private final static Logger logger = LoggerFactory.getLogger(SmartParkAttendanceRecordServiceImpl.class);

    @Resource
    private SmartParkAttendanceRecordMapper smartParkAttendanceRecordMapper;
    @Resource
    private SmartParkAttendanceRecordDetailMapper smartParkAttendanceRecordDetailMapper;
    @Resource
    private SmartParkGroupWhiteListMapper smartParkGroupWhiteListMapper;
    @Resource
    private SmartParkGroupObjectMapper smartParkGroupObjectMapper;
    @Resource
    private SmartParkAttendanceGroupMapper smartParkAttendanceGroupMapper;
    @Resource
    private SmartParkGroupAccessControlMapper smartParkGroupAccessControlMapper;
    @Resource
    private SmartParkGroupSpecialDateMapper smartParkGroupSpecialDateMapper;
    @Resource
    private SmartParkHolidayDetailService smartParkHolidayDetailService;
    @Resource
    private SmartParkGroupWeekdaysMapper smartParkGroupWeekdaysMapper;
    @Resource
    private SmartParkShiftMapper smartParkShiftMapper;
    @Resource
    private SmartParkShiftDetailsMapper smartParkShiftDetailsMapper;
    @Resource
    private SmartParkAttendanceUserOccupyMapper smartParkAttendanceUserOccupyMapper;
    @Resource
    private SmartParkAccessControlPassRecordMapper smartParkAccessControlPassRecordMapper;
    @Resource
    private AclUserRpcService aclUserRpcService;
    @Resource
    private SmartParkAttendanceApproveMapper smartParkAttendanceApproveMapper;
    @Resource
    private SmartParkVacationTypeMapper smartParkVacationTypeMapper;



    /**
     * @param smartParkAttendanceRecordQO:
     * @Description: 分页查询
     * @Author: ChenYong
     * @Date: 2021/8/3 0003
     * @Return: CommonResponseBody<List < SmartParkAttendanceRecordVO>>
     */
    @Override
    public CommonResponseBody<List<SmartParkAttendanceRecordVO>> getAttendanceRecords(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {

        SmartParkAttendanceRecordExample recordExample = new SmartParkAttendanceRecordExample();
        SmartParkAttendanceRecordExample.Criteria criteria = recordExample.createCriteria();
        criteria.andIsDeletedEqualTo(0);
        if (StringUtils.isBlank(smartParkAttendanceRecordQO.getTenantId())) {
            return ResponseBodyWrapperUtil.fail(ErrMsgEnum.EMPTY_PARAME.getErrorMessage(), ErrMsgEnum.EMPTY_PARAME.getErrorCode());
        }
        if (StringUtils.isNotBlank(smartParkAttendanceRecordQO.getTenantId())) {
            criteria.andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId());
        }
        if (smartParkAttendanceRecordQO.getClockInDate() != null && !"".equals(smartParkAttendanceRecordQO.getClockInDate())) {
            criteria.andClockInDateEqualTo(smartParkAttendanceRecordQO.getClockInDate());
        }
        if (StringUtils.isNotBlank(smartParkAttendanceRecordQO.getUserName())) {
            criteria.andUserNameEqualTo(smartParkAttendanceRecordQO.getUserName());
        }
        if (smartParkAttendanceRecordQO.getUserId() != null) {
            criteria.andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId());
        }
        if (smartParkAttendanceRecordQO.getClockInWay() != null) {
            criteria.andClockInWayEqualTo(smartParkAttendanceRecordQO.getClockInWay());
        }
        //查询异常的记录（迟到，早退，旷工，外勤）
        if (smartParkAttendanceRecordQO.getWhetherAbnormally()!=null && smartParkAttendanceRecordQO.getWhetherAbnormally()) {
            List<Integer> list = new ArrayList<>();
            list.add(2);
            list.add(3);
            list.add(4);
            criteria.andClockInStatusIn(list);
            recordExample.or().andFieldWorkEqualTo(1);
        }
        //获取当前登录信息查询所在部门，根据所在部门查询打卡记录
        SsoUserRpcQO ssoUserRpcQO = new SsoUserRpcQO();
        SsoUserDTO ssoUserDTO = UserHolderContext.getUser();
        ssoUserRpcQO.setUserId(ssoUserDTO!=null?String.valueOf(ssoUserDTO.getUserId()):"");
        CommonResponseBody<SsoUserRpcQO> userDetail = aclUserRpcService.getUserDetail(ssoUserRpcQO);
        List<Long> longList = new ArrayList<>();
        if(userDetail.getData()!=null){
            List<SsoDeptDTO> deptList = userDetail.getData().getDeptList();
            if(deptList!=null){
                for (SsoDeptDTO ssoDeptDTO:deptList){
                    longList.add(Long.valueOf(ssoDeptDTO.getDeptCode()));
                }
                recordExample.or().andDeptIdIn(longList);
            }
        }

        if (smartParkAttendanceRecordQO.getNeedPage()) {
            recordExample.setOrderByClause("gmt_create desc limit " + (smartParkAttendanceRecordQO.getPageIndex() - 1) * smartParkAttendanceRecordQO.getPageSize() + "," + smartParkAttendanceRecordQO.getPageSize());
        } else {
            recordExample.setOrderByClause("gmt_create asc");
        }

        List<SmartParkAttendanceRecord> passRecords = smartParkAttendanceRecordMapper.selectByExample(recordExample);
        long count = smartParkAttendanceRecordMapper.countByExample(recordExample);

        return ResponseBodyWrapperUtil
                .successListWrapper(passRecords, count, smartParkAttendanceRecordQO, SmartParkAttendanceRecordVO.class);
    }

    /**
     * @param smartParkAttendanceRecordQO:
     * @Description: 保存打卡记录
     * @Author: ChenYong
     * @Date: 2021/8/3 0003
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody saveAttendanceRecord(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {
        int insert = 0;
        String simpleDateFormat = "HH:mm";
        String format = "yyyy-MM-dd HH:mm:ss";
        String clockInDateFormat = "yyyy-MM-dd";
        //打卡日期
        String clockInDate = DateUtil.format(smartParkAttendanceRecordQO.getClockInTime(), clockInDateFormat);
        try {

            if (smartParkAttendanceRecordQO.getUserId() == null) {
                System.out.print("用户ID不能为空");
                return ResponseBodyWrapperUtil.fail("用户ID不能为空", "80013");
            }
            if (smartParkAttendanceRecordQO.getClockInTime() == null) {
                System.out.print("打卡时间不能为空");
                return ResponseBodyWrapperUtil.fail("打卡时间不能为空", "80014");
            }
            if (smartParkAttendanceRecordQO.getTenantId() == null) {
                System.out.print("租户ID不能为空");
                return ResponseBodyWrapperUtil.fail("租户ID不能为空", "80016");
            }

            //判断是否有占用信息
            SmartParkAttendanceUserOccupy smartParkAttendanceUserOccupy = new SmartParkAttendanceUserOccupy();
            smartParkAttendanceUserOccupy.setNowDate(smartParkAttendanceRecordQO.getClockInTime());
            smartParkAttendanceUserOccupy.setUserId(smartParkAttendanceRecordQO.getUserId());
            List<SmartParkAttendanceUserOccupy> smartParkAttendanceUserOccupies = smartParkAttendanceUserOccupyMapper.selectByTime(smartParkAttendanceUserOccupy);
            if (smartParkAttendanceUserOccupies.size() > 0) {
                return ResponseBodyWrapperUtil.fail("当前用户" + smartParkAttendanceUserOccupies.get(0).getBusinessType() + "中", "80021");
            }

            List<SmartParkGroupWhiteList> smartParkGroupWhiteLists = new ArrayList<>();
            if (smartParkAttendanceRecordQO.getUserId() != null) {
                SmartParkGroupWhiteListExample smartParkGroupWhiteListExample = new SmartParkGroupWhiteListExample();
                smartParkGroupWhiteListExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                smartParkGroupWhiteLists = smartParkGroupWhiteListMapper.selectByExample(smartParkGroupWhiteListExample);
            }
            if (smartParkGroupWhiteLists.size() > 0) {
                return ResponseBodyWrapperUtil.fail("当前用户为考勤白名单", "80001");
            }

            //考勤对象，判断用户是否绑定考勤组
            List<SmartParkGroupObject> smartParkGroupObjects = new ArrayList<>();
            if (smartParkAttendanceRecordQO.getUserId() != null) {
                SmartParkGroupObjectExample smartParkGroupObjectExample = new SmartParkGroupObjectExample();
                smartParkGroupObjectExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                ;
                smartParkGroupObjects = smartParkGroupObjectMapper.selectByExample(smartParkGroupObjectExample);
            }
            if (smartParkGroupObjects.size() < 1) {
                return ResponseBodyWrapperUtil.fail("当前用户未绑定考勤组", "80001");
            }

            //考勤组信息
            SmartParkAttendanceGroup smartParkAttendanceGroup = smartParkAttendanceGroupMapper.selectByPrimaryKey(smartParkGroupObjects.get(0).getGroupId());
            if (smartParkAttendanceGroup == null) {
                return ResponseBodyWrapperUtil.fail("未获取到考勤组信息", "80002");
            }
            if (smartParkAttendanceGroup.getEnableStatus() == 0) {
                return ResponseBodyWrapperUtil.fail("考勤组未启用", "80010");
            }

            if (smartParkAttendanceRecordQO.getClockInWay() == 1) {

                //判断当前数据打卡来源是否在考勤组门禁设备列表内
                SmartParkGroupAccessControlExample smartParkGroupAccessControlExample = new SmartParkGroupAccessControlExample();
                smartParkGroupAccessControlExample.or().andAccessControlIdEqualTo(smartParkAttendanceRecordQO.getClockInSource())
                        .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andAccessControlIdEqualTo(smartParkAttendanceRecordQO.getClockInSource())
                        .andIsDeletedEqualTo(0);
                ;
                List<SmartParkGroupAccessControl> smartParkGroupAccessControls = smartParkGroupAccessControlMapper.selectByExample(smartParkGroupAccessControlExample);
                if (smartParkGroupAccessControls.size() < 0) {
                    return ResponseBodyWrapperUtil.fail("考勤组未绑定当前打卡来源的设备", "80003");
                }

                if (smartParkAttendanceGroup.getEntranceGuardEnableStatus() == 0) {
                    return ResponseBodyWrapperUtil.fail("门禁打卡未启用", "80011");
                }
            }
            if (smartParkAttendanceRecordQO.getClockInWay() == 2) {
                if (smartParkAttendanceGroup.getAppClockInEnableStatus() == 0) {
                    return ResponseBodyWrapperUtil.fail("APP打卡未启用", "80012");
                }
            }


            //判断当天是否为特殊日期
            SmartParkGroupSpecialDateExample smartParkGroupSpecialDateExample = new SmartParkGroupSpecialDateExample();
            Date handle = DateTimeUtil.handle(smartParkAttendanceRecordQO.getClockInTime(), 00, 00);
            smartParkGroupSpecialDateExample.or().andSpecialDateEqualTo(handle)
                    .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                    .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                    .andIsDeletedEqualTo(0);
            List<SmartParkGroupSpecialDate> smartParkGroupSpecialDates = smartParkGroupSpecialDateMapper.selectByExample(smartParkGroupSpecialDateExample);
            Long shiftId = null;
            //是否需要打卡
            boolean status = false;
            //是否是加班
            boolean workOvertimeStatus = false;
            //是否存入记录表
            boolean recordStatus = false;
            //打卡时间的工作日
            int weekDay = 0;
            if (smartParkGroupSpecialDates.size() > 0) {
                //当前日期为特殊日期
                //如果是判断是否需要上班
                if (smartParkGroupSpecialDates.get(0).getShiftId() != 0) {
                    shiftId = smartParkGroupSpecialDates.get(0).getShiftId();
                    //需要打卡
                    status = true;
                } else {
                    workOvertimeStatus = true;
                    //return ResponseBodyWrapperUtil.fail("当前日期为休息日", "80004");
                }
            } else {
                //当前日期不是特殊日期
                //获取节假日信息
                String times = DateUtil.format(smartParkAttendanceRecordQO.getClockInTime(), format);
                SmartParkHolidayDetailQO smartParkHolidayDetailQO = new SmartParkHolidayDetailQO();
                smartParkHolidayDetailQO.setTimes(times);
                CommonResponseBody commonResponseBody = smartParkHolidayDetailService.queryByDate(smartParkHolidayDetailQO);
                //判断是否需要打卡
                if (commonResponseBody.getData() !=null) {
                    //需要打卡
                    //获取工作日班次信息
                    weekDay = DateTimeUtil.getWeekDay(smartParkAttendanceRecordQO.getClockInTime());
                    SmartParkGroupWeekdaysExample smartParkGroupWeekdaysExample = new SmartParkGroupWeekdaysExample();
                    smartParkGroupWeekdaysExample.or().andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                            .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                            .andWeekDayNumEqualTo(weekDay)
                            .andIsDeletedEqualTo(0);
                    List<SmartParkGroupWeekdays> smartParkGroupWeekdays = smartParkGroupWeekdaysMapper.selectByExample(smartParkGroupWeekdaysExample);
                    if (smartParkGroupWeekdays.size() < 1) {
                        workOvertimeStatus = true;
                        return ResponseBodyWrapperUtil.fail("未获取到对应的工作日信息", "80005");
                    }
                    shiftId = smartParkGroupWeekdays.get(0).getShiftId();
                    status = true;
                } else {
                    workOvertimeStatus = true;
                    //return ResponseBodyWrapperUtil.fail("当前日期为休息日", "80004");
                }
            }

            //转换实体
            SmartParkAttendanceRecord smartParkAttendanceRecord = new SmartParkAttendanceRecord();
            BeanUtil.conversion(smartParkAttendanceRecordQO, smartParkAttendanceRecord);

            //需要打卡获取班次打卡时间段
            if (status) {
                SmartParkShift smartParkShift = new SmartParkShift();
                if (shiftId != null && shiftId != 0) {
                    smartParkShift = smartParkShiftMapper.selectByPrimaryKey(shiftId);
                    if (smartParkShift == null) {
                        return ResponseBodyWrapperUtil.fail("未获取到班次信息", "80007");
                    }
                    if (smartParkShift.getEnableStatus() == 0) {
                        return ResponseBodyWrapperUtil.fail("当前班次未启用", "80009");
                    }
                } else {
                    workOvertimeStatus = true;
                    //return ResponseBodyWrapperUtil.fail("当前日期为休息日或班次ID为空", "80008");
                }

                //考勤状态
                Integer clockInStatus = 1;
                //考勤状态名
                String clockInStatusName = "正常";
                //异常分钟数
                int minutes = 0;
                //加班分钟数
                int workOvertimeMinutes = 0;
                String shiftWorkTime = "";
                //是否是签到
                boolean isSignIn = true;

                //获取班次所有打卡时间段，判断是在哪一个时间段内
                SmartParkShiftDetails shiftDetails = new SmartParkShiftDetails();

                SmartParkShiftDetailsExample smartParkShiftDetailsExample = new SmartParkShiftDetailsExample();
                smartParkShiftDetailsExample.or().andShiftIdEqualTo(shiftId)
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                List<SmartParkShiftDetails> smartParkShiftDetailsList = smartParkShiftDetailsMapper.selectByExample(smartParkShiftDetailsExample);
                for (SmartParkShiftDetails smartParkShiftDetails : smartParkShiftDetailsList) {

                    String clockTime = DateUtil.format(smartParkAttendanceRecordQO.getClockInTime(), simpleDateFormat);
                    //判断当前时间是否在签到时间段内
                    boolean signInTimeBoolean = DateTimeUtil.isEffectiveDate(clockTime, smartParkShiftDetails.getSignInStartTime(), smartParkShiftDetails.getSignInEndTime());
                    //判断当前时间是否在签退时间段内
                    boolean signOutTimeBoolean = DateTimeUtil.isEffectiveDate(clockTime, smartParkShiftDetails.getSignOutStartTime(), smartParkShiftDetails.getSignOutEndTime());
                    if (signInTimeBoolean) {
                        shiftDetails = smartParkShiftDetails;
                        //判断打卡时间是否大于签到时间
                        Date parse = DateUtil.parse(clockTime, simpleDateFormat);
                        Date signInTime = DateUtil.parse(smartParkShiftDetails.getSignInTime(), simpleDateFormat);
                        //判断打卡时间是否在签到时间之后
                        boolean after = parse.after(signInTime);
                        minutes = (int) ((parse.getTime() - signInTime.getTime()) / (1000 * 60));

                        if (after && minutes > Integer.valueOf(smartParkShift.getNoRememberLateMinutes())) {
                            clockInStatus = 2;
                            clockInStatusName = "迟到";
                        }
                        if (after && minutes > Integer.valueOf(smartParkShift.getLateMinutesAbsenteeism())) {
                            clockInStatus = 4;
                            clockInStatusName = "旷工";
                        }
                        shiftWorkTime = shiftDetails.getSignInTime();
                        recordStatus = true;
                        smartParkAttendanceRecord.setClockInType(1);
                        smartParkAttendanceRecord.setClockInTypeName("签到");
                    } else if (signOutTimeBoolean) {
                        shiftDetails = smartParkShiftDetails;
                        //判断打卡时间是否小于签退时间
                        Date parse = DateUtil.parse(clockTime, simpleDateFormat);
                        Date signOutTime = DateUtil.parse(smartParkShiftDetails.getSignOutTime(), simpleDateFormat);

                        //判断打卡时间是否在签退时间之前
                        boolean before = parse.before(signOutTime);
                        minutes = (int) ((signOutTime.getTime() - parse.getTime()) / (1000 * 60));

                        if (before && minutes > Integer.valueOf(smartParkShift.getNoRememberLateMinutes())) {
                            clockInStatus = 3;
                            clockInStatusName = "早退";
                        }
                        if (before && minutes > Integer.valueOf(smartParkShift.getLateMinutesAbsenteeism())) {
                            clockInStatus = 4;
                            clockInStatusName = "旷工";
                        }

                        if(!before&&parse.after(DateUtil.parse(smartParkShift.getWorkOvertimeStartTime(), simpleDateFormat))){
                            //计算出来的加班时间
                            workOvertimeMinutes = (int) ((parse.getTime() - DateUtil.parse(smartParkShift.getWorkOvertimeStartTime(), simpleDateFormat).getTime()) / (1000 * 60));
                            clockInStatus = 6;
                            clockInStatusName = "加班";
                        }
                        isSignIn = false;
                        recordStatus = true;
                        shiftWorkTime = shiftDetails.getSignOutTime();

                        smartParkAttendanceRecord.setClockInType(2);
                        smartParkAttendanceRecord.setClockInTypeName("签退");
                    } else {
                        return ResponseBodyWrapperUtil.fail("当前时间不在打卡时间段内，不能进行打卡。", "80012");
                    }
                }

                smartParkAttendanceRecord.setUserName(smartParkAttendanceRecordQO.getUserName());
                smartParkAttendanceRecord.setDeptId(smartParkAttendanceRecordQO.getDeptId());
                smartParkAttendanceRecord.setDeptName(smartParkAttendanceRecordQO.getDeptName());
                smartParkAttendanceRecord.setUserId(smartParkAttendanceRecordQO.getUserId());
                if(minutes<0){
                    minutes = 0;
                }
                smartParkAttendanceRecord.setAbnormalMinutes(minutes);
                if(workOvertimeMinutes<0){
                    workOvertimeMinutes = 0;
                }
                smartParkAttendanceRecord.setWorkOvertimeMinutes(workOvertimeMinutes);
                smartParkAttendanceRecord.setClockInTime(smartParkAttendanceRecordQO.getClockInTime());
                smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                smartParkAttendanceRecord.setClockInStatusName(clockInStatusName);
                smartParkAttendanceRecord.setCardShift(smartParkShift.getId());
                smartParkAttendanceRecord.setCardShiftName(smartParkShift.getShiftName());
                smartParkAttendanceRecord.setGroupId(smartParkAttendanceGroup.getId());
                smartParkAttendanceRecord.setGroupName(smartParkAttendanceGroup.getAttendanceGroupName());
                smartParkAttendanceRecord.setClockInWeek(weekDay);
                smartParkAttendanceRecord.setDispose(0);
                smartParkAttendanceRecord.setShiftWorkTime(shiftWorkTime);
                smartParkAttendanceRecord.setCardSupplement(0);
                if(smartParkAttendanceRecordQO.getFieldWork() == null){
                    smartParkAttendanceRecord.setFieldWork(0);
                }
                smartParkAttendanceRecord.setClockInDate(clockInDate);
                smartParkAttendanceRecord.setCreator(String.valueOf(smartParkAttendanceRecordQO.getUserId()));
                smartParkAttendanceRecord.beforeInsert();

                //存入打卡流水表
                SmartParkAttendanceRecordDetail smartParkAttendanceRecordDetail = new SmartParkAttendanceRecordDetail();
                BeanUtil.conversion(smartParkAttendanceRecord, smartParkAttendanceRecordDetail);
                smartParkAttendanceRecordDetail.beforeInsert();

                insert = smartParkAttendanceRecordDetailMapper.insert(smartParkAttendanceRecordDetail);

                if (recordStatus) {
                    SmartParkAttendanceRecordExample smartParkAttendanceRecordExample = new SmartParkAttendanceRecordExample();
                    smartParkAttendanceRecordExample.or().andUserIdEqualTo(smartParkAttendanceRecord.getUserId())
                            .andDeptIdEqualTo(smartParkAttendanceRecord.getDeptId())
                            .andCardShiftEqualTo(smartParkAttendanceRecord.getCardShift())
                            .andGroupIdEqualTo(smartParkAttendanceRecord.getGroupId())
                            .andShiftWorkTimeEqualTo(shiftWorkTime)
                            .andClockInDateEqualTo(clockInDate)
                            .andIsDeletedEqualTo(0);
                    List<SmartParkAttendanceRecord> smartParkAttendanceRecords = smartParkAttendanceRecordMapper.selectByExample(smartParkAttendanceRecordExample);
                    //查询当前人在当前班次打卡段是否打过卡
                    if (smartParkAttendanceRecords.size() > 0) {
                        smartParkAttendanceRecord = smartParkAttendanceRecords.get(0);
                        if (isSignIn) {
                            //如果是签到，当前时间在记录时间之前更新，之后不做操作
                            if (smartParkAttendanceRecordQO.getClockInTime().before(smartParkAttendanceRecord.getClockInTime())) {
                                smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                                smartParkAttendanceRecord.setClockInStatusName(clockInStatusName);
                                smartParkAttendanceRecord.setAbnormalMinutes(minutes);
                                smartParkAttendanceRecord.setClockInTime(smartParkAttendanceRecordQO.getClockInTime());
                                insert = smartParkAttendanceRecordMapper.updateByPrimaryKey(smartParkAttendanceRecord);
                            }
                        } else {
                            //如果是签退，当前时间在记录时间之后更新，之前不做操作
                            if (smartParkAttendanceRecordQO.getClockInTime().after(smartParkAttendanceRecord.getClockInTime())) {
                                smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                                smartParkAttendanceRecord.setClockInStatusName(clockInStatusName);
                                smartParkAttendanceRecord.setAbnormalMinutes(minutes);
                                smartParkAttendanceRecord.setWorkOvertimeMinutes(workOvertimeMinutes);
                                smartParkAttendanceRecord.setClockInTime(smartParkAttendanceRecordQO.getClockInTime());
                                insert = smartParkAttendanceRecordMapper.updateByPrimaryKey(smartParkAttendanceRecord);
                            }
                        }
                    } else {
                        insert = smartParkAttendanceRecordMapper.insert(smartParkAttendanceRecord);
                    }
                }
                if(workOvertimeStatus){
                    SmartParkAttendanceRecordExample smartParkAttendanceRecordExample = new SmartParkAttendanceRecordExample();
                    smartParkAttendanceRecordExample.or().andUserIdEqualTo(smartParkAttendanceRecord.getUserId())
                            .andDeptIdEqualTo(smartParkAttendanceRecord.getDeptId())
                            .andGroupIdEqualTo(smartParkAttendanceRecord.getGroupId())
                            .andClockInDateEqualTo(clockInDate)
                            .andIsDeletedEqualTo(0);
                    smartParkAttendanceRecordExample.setOrderByClause("clock_in_time desc limit 1");
                    List<SmartParkAttendanceRecord> smartParkAttendanceRecords = smartParkAttendanceRecordMapper.selectByExample(smartParkAttendanceRecordExample);
                    smartParkAttendanceRecord.setClockInType(3);
                    smartParkAttendanceRecord.setClockInTypeName("加班");
                    smartParkAttendanceRecord.setClockInStatus(6);
                    smartParkAttendanceRecord.setClockInStatusName("加班");
                    smartParkAttendanceRecord.setClockInTime(smartParkAttendanceRecordQO.getClockInTime());
                    //查询当前人当天是否打过卡
                    if (smartParkAttendanceRecords.size() > 0) {
                        SmartParkAttendanceRecord  previousSmartParkAttendanceRecord = smartParkAttendanceRecords.get(0);
                        //计算出来的加班时间
                        workOvertimeMinutes = (int) ((smartParkAttendanceRecord.getClockInTime().getTime() - previousSmartParkAttendanceRecord.getClockInTime().getTime()) / (1000 * 60));
                        smartParkAttendanceRecord.setWorkOvertimeMinutes(workOvertimeMinutes);
                    }
                    insert = smartParkAttendanceRecordMapper.insert(smartParkAttendanceRecord);
                }

            }
            return ResponseBodyWrapperUtil.toResData(insert);
        } catch (Exception e) {
            logger.error("", e);
            return ResponseBodyWrapperUtil.fail(ErrMsgEnum.ERROR_SYSTEM.getErrorMessage(), ErrMsgEnum.ERROR_SYSTEM.getErrorCode());
        }

    }

    /**
     * 保存APP打卡
     * @Description:  保存APP打卡
     * @Author: ChenYong
     * @Date: 2021/9/3 0003
     * @param smartParkAttendanceRecordQO:
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody saveAppAttendanceRecord(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {
        int insert = 0;
        String simpleDateFormat = "HH:mm";
        String format = "yyyy-MM-dd HH:mm:ss";
        String clockInDateFormat = "yyyy-MM-dd";
        //打卡日期
        String clockInDate = DateUtil.format(smartParkAttendanceRecordQO.getClockInTime(), clockInDateFormat);
        try {

            if (smartParkAttendanceRecordQO.getUserId() == null) {
                System.out.print("用户ID不能为空");
                return ResponseBodyWrapperUtil.fail("用户ID不能为空", "80013");
            }
            if (smartParkAttendanceRecordQO.getClockInTime() == null) {
                System.out.print("打卡时间不能为空");
                return ResponseBodyWrapperUtil.fail("打卡时间不能为空", "80014");
            }
            if (smartParkAttendanceRecordQO.getTenantId() == null) {
                System.out.print("租户ID不能为空");
                return ResponseBodyWrapperUtil.fail("租户ID不能为空", "80016");
            }

            //判断是否有占用信息
            SmartParkAttendanceUserOccupy smartParkAttendanceUserOccupy = new SmartParkAttendanceUserOccupy();
            smartParkAttendanceUserOccupy.setNowDate(smartParkAttendanceRecordQO.getClockInTime());
            smartParkAttendanceUserOccupy.setUserId(smartParkAttendanceRecordQO.getUserId());
            List<SmartParkAttendanceUserOccupy> smartParkAttendanceUserOccupies = smartParkAttendanceUserOccupyMapper.selectByTime(smartParkAttendanceUserOccupy);
            if (smartParkAttendanceUserOccupies.size() > 0) {
                return ResponseBodyWrapperUtil.fail("当前用户" + smartParkAttendanceUserOccupies.get(0).getBusinessType() + "中", "80021");
            }

            List<SmartParkGroupWhiteList> smartParkGroupWhiteLists = new ArrayList<>();
            if (smartParkAttendanceRecordQO.getUserId() != null) {
                SmartParkGroupWhiteListExample smartParkGroupWhiteListExample = new SmartParkGroupWhiteListExample();
                smartParkGroupWhiteListExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                ;
                smartParkGroupWhiteLists = smartParkGroupWhiteListMapper.selectByExample(smartParkGroupWhiteListExample);
            }
            if (smartParkGroupWhiteLists.size() > 0) {
                return ResponseBodyWrapperUtil.fail("当前用户为考勤白名单", "80001");
            }

            //考勤对象，判断用户是否绑定考勤组
            List<SmartParkGroupObject> smartParkGroupObjects = new ArrayList<>();
            if (smartParkAttendanceRecordQO.getUserId() != null) {
                SmartParkGroupObjectExample smartParkGroupObjectExample = new SmartParkGroupObjectExample();
                smartParkGroupObjectExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                ;
                smartParkGroupObjects = smartParkGroupObjectMapper.selectByExample(smartParkGroupObjectExample);
            }
            if (smartParkGroupObjects.size() < 1) {
                return ResponseBodyWrapperUtil.fail("当前用户未绑定考勤组", "80001");
            }

            //考勤组信息
            SmartParkAttendanceGroup smartParkAttendanceGroup = smartParkAttendanceGroupMapper.selectByPrimaryKey(smartParkGroupObjects.get(0).getGroupId());
            if (smartParkAttendanceGroup == null) {
                return ResponseBodyWrapperUtil.fail("未获取到考勤组信息", "80002");
            }
            if (smartParkAttendanceGroup.getEnableStatus() == 0) {
                return ResponseBodyWrapperUtil.fail("考勤组未启用", "80010");
            }

            if (smartParkAttendanceRecordQO.getClockInWay() == 1) {

                //判断当前数据打卡来源是否在考勤组门禁设备列表内
                SmartParkGroupAccessControlExample smartParkGroupAccessControlExample = new SmartParkGroupAccessControlExample();
                smartParkGroupAccessControlExample.or().andAccessControlIdEqualTo(smartParkAttendanceRecordQO.getClockInSource())
                        .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andAccessControlIdEqualTo(smartParkAttendanceRecordQO.getClockInSource())
                        .andIsDeletedEqualTo(0);
                ;
                List<SmartParkGroupAccessControl> smartParkGroupAccessControls = smartParkGroupAccessControlMapper.selectByExample(smartParkGroupAccessControlExample);
                if (smartParkGroupAccessControls.size() < 0) {
                    return ResponseBodyWrapperUtil.fail("考勤组未绑定当前打卡来源的设备", "80003");
                }

                if (smartParkAttendanceGroup.getEntranceGuardEnableStatus() == 0) {
                    return ResponseBodyWrapperUtil.fail("门禁打卡未启用", "80011");
                }
            }
            if (smartParkAttendanceRecordQO.getClockInWay() == 2) {
                if (smartParkAttendanceGroup.getAppClockInEnableStatus() == 0) {
                    return ResponseBodyWrapperUtil.fail("APP打卡未启用", "80012");
                }
            }

            //判断当天是否为特殊日期
            SmartParkGroupSpecialDateExample smartParkGroupSpecialDateExample = new SmartParkGroupSpecialDateExample();
            Date handle = DateTimeUtil.handle(smartParkAttendanceRecordQO.getClockInTime(), 00, 00);
            smartParkGroupSpecialDateExample.or().andSpecialDateEqualTo(handle)
                    .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                    .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                    .andIsDeletedEqualTo(0);
            List<SmartParkGroupSpecialDate> smartParkGroupSpecialDates = smartParkGroupSpecialDateMapper.selectByExample(smartParkGroupSpecialDateExample);
            Long shiftId = null;
            //是否需要打卡
            boolean status;
            //是否存入记录表
            boolean recordStatus = false;
            //打卡时间的工作日
            int weekDay = 0;
            if (smartParkGroupSpecialDates.size() > 0) {
                //当前日期为特殊日期
                //如果是判断是否需要上班
                if (smartParkGroupSpecialDates.get(0).getShiftId() != 0) {
                    shiftId = smartParkGroupSpecialDates.get(0).getShiftId();
                    //需要打卡
                    status = true;
                } else {
                    return ResponseBodyWrapperUtil.fail("当前日期为休息日", "80004");
                }
            } else {
                //当前日期不是特殊日期
                //获取节假日信息
                String times = DateUtil.format(smartParkAttendanceRecordQO.getClockInTime(), format);
                SmartParkHolidayDetailQO smartParkHolidayDetailQO = new SmartParkHolidayDetailQO();
                smartParkHolidayDetailQO.setTimes(times);
                smartParkHolidayDetailQO.setTenantId(smartParkAttendanceRecordQO.getTenantId());
                CommonResponseBody commonResponseBody = smartParkHolidayDetailService.queryByDate(smartParkHolidayDetailQO);
                //判断是否需要打卡
                if ((Boolean) commonResponseBody.getData()) {
                    //需要打卡
                    //获取工作日班次信息
                    weekDay = DateTimeUtil.getWeekDay(smartParkAttendanceRecordQO.getClockInTime());
                    SmartParkGroupWeekdaysExample smartParkGroupWeekdaysExample = new SmartParkGroupWeekdaysExample();
                    smartParkGroupWeekdaysExample.or().andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                            .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                            .andWeekDayNumEqualTo(weekDay)
                            .andIsDeletedEqualTo(0);
                    List<SmartParkGroupWeekdays> smartParkGroupWeekdays = smartParkGroupWeekdaysMapper.selectByExample(smartParkGroupWeekdaysExample);
                    if (smartParkGroupWeekdays.size() < 1) {
                        return ResponseBodyWrapperUtil.fail("未获取到对应的工作日信息", "80005");
                    }
                    shiftId = smartParkGroupWeekdays.get(0).getShiftId();
                    status = true;
                } else {
                    return ResponseBodyWrapperUtil.fail("当前日期为休息日", "80004");
                }
            }

            //转换实体
            SmartParkAttendanceRecord smartParkAttendanceRecord = new SmartParkAttendanceRecord();
            BeanUtil.conversion(smartParkAttendanceRecordQO, smartParkAttendanceRecord);

            //需要打卡获取班次打卡时间段
            if (status) {
                SmartParkShift smartParkShift = new SmartParkShift();
                if (shiftId != null && shiftId != 0) {
                    smartParkShift = smartParkShiftMapper.selectByPrimaryKey(shiftId);
                    if (smartParkShift == null) {
                        return ResponseBodyWrapperUtil.fail("未获取到班次信息", "80007");
                    }
                    if (smartParkShift.getEnableStatus() == 0) {
                        return ResponseBodyWrapperUtil.fail("当前班次未启用", "80009");
                    }
                } else {
                    return ResponseBodyWrapperUtil.fail("当前日期为休息日或班次ID为空", "80008");
                }

                //考勤状态
                Integer clockInStatus = 1;
                //考勤状态名
                String clockInStatusName = "正常";
                //异常分钟数
                int minutes = 0;

                String shiftWorkTime = "";
                //是否是签到
                boolean isSignIn = true;

                //获取班次所有打卡时间段，判断是在哪一个时间段内
                SmartParkShiftDetails shiftDetails = new SmartParkShiftDetails();

                SmartParkShiftDetailsExample smartParkShiftDetailsExample = new SmartParkShiftDetailsExample();
                smartParkShiftDetailsExample.or().andShiftIdEqualTo(shiftId)
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                List<SmartParkShiftDetails> smartParkShiftDetailsList = smartParkShiftDetailsMapper.selectByExample(smartParkShiftDetailsExample);
                for (SmartParkShiftDetails smartParkShiftDetails : smartParkShiftDetailsList) {

                    String clockTime = DateUtil.format(smartParkAttendanceRecordQO.getClockInTime(), simpleDateFormat);
                    //判断当前时间是否在签到时间段内
                    boolean signInTimeBoolean = DateTimeUtil.isEffectiveDate(clockTime, smartParkShiftDetails.getSignInStartTime(), smartParkShiftDetails.getSignInEndTime());
                    //判断当前时间是否在签退时间段内
                    boolean signOutTimeBoolean = DateTimeUtil.isEffectiveDate(clockTime, smartParkShiftDetails.getSignOutStartTime(), smartParkShiftDetails.getSignOutEndTime());
                    if (signInTimeBoolean) {
                        shiftDetails = smartParkShiftDetails;
                        //判断打卡时间是否大于签到时间
                        Date parse = DateUtil.parse(clockTime, simpleDateFormat);
                        Date signInTime = DateUtil.parse(smartParkShiftDetails.getSignInTime(), simpleDateFormat);

                        boolean after = parse.after(signInTime);
                        minutes = (int) ((parse.getTime() - signInTime.getTime()) / (1000 * 60));

                        if (after && minutes > Integer.valueOf(smartParkShift.getNoRememberLateMinutes())) {
                            clockInStatus = 2;
                            clockInStatusName = "迟到";
                        }
                        if (after && minutes > Integer.valueOf(smartParkShift.getLateMinutesAbsenteeism())) {
                            clockInStatus = 4;
                            clockInStatusName = "旷工";
                        }
                        shiftWorkTime = shiftDetails.getSignInTime();
                        recordStatus = true;
                        smartParkAttendanceRecord.setClockInType(1);
                        smartParkAttendanceRecord.setClockInTypeName("签到");
                    } else if (signOutTimeBoolean) {
                        shiftDetails = smartParkShiftDetails;
                        //判断打卡时间是否小于签退时间
                        Date parse = DateUtil.parse(clockTime, simpleDateFormat);
                        Date signOutTime = DateUtil.parse(smartParkShiftDetails.getSignOutTime(), simpleDateFormat);
                        ;

                        boolean before = parse.before(signOutTime);
                        minutes = (int) ((signOutTime.getTime() - parse.getTime()) / (1000 * 60));

                        if (before && minutes > Integer.valueOf(smartParkShift.getNoRememberLateMinutes())) {
                            clockInStatus = 3;
                            clockInStatusName = "早退";
                        }
                        if (before && minutes > Integer.valueOf(smartParkShift.getLateMinutesAbsenteeism())) {
                            clockInStatus = 4;
                            clockInStatusName = "旷工";
                        }
                        isSignIn = false;
                        recordStatus = true;
                        shiftWorkTime = shiftDetails.getSignOutTime();

                        smartParkAttendanceRecord.setClockInType(2);
                        smartParkAttendanceRecord.setClockInTypeName("签退");
                    } else {
                        return ResponseBodyWrapperUtil.fail("当前时间不在打卡时间段内，不能进行打卡。", "80012");
                    }
                }

                smartParkAttendanceRecord.setUserName(smartParkAttendanceRecordQO.getUserName());
                smartParkAttendanceRecord.setDeptId(smartParkAttendanceRecordQO.getDeptId());
                smartParkAttendanceRecord.setDeptName(smartParkAttendanceRecordQO.getDeptName());
                smartParkAttendanceRecord.setUserId(smartParkAttendanceRecordQO.getUserId());
                if(minutes<0){
                    minutes = 0;
                }
                smartParkAttendanceRecord.setAbnormalMinutes(minutes);
                smartParkAttendanceRecord.setClockInTime(smartParkAttendanceRecordQO.getClockInTime());
                smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                smartParkAttendanceRecord.setClockInStatusName(clockInStatusName);
                smartParkAttendanceRecord.setCardShift(smartParkShift.getId());
                smartParkAttendanceRecord.setCardShiftName(smartParkShift.getShiftName());
                smartParkAttendanceRecord.setGroupId(smartParkAttendanceGroup.getId());
                smartParkAttendanceRecord.setGroupName(smartParkAttendanceGroup.getAttendanceGroupName());
                smartParkAttendanceRecord.setClockInWeek(weekDay);
                smartParkAttendanceRecord.setDispose(0);
                smartParkAttendanceRecord.setShiftWorkTime(shiftWorkTime);
                smartParkAttendanceRecord.setCardSupplement(0);
                if(smartParkAttendanceRecordQO.getFieldWork() == null){
                    smartParkAttendanceRecord.setFieldWork(0);
                }
                smartParkAttendanceRecord.setClockInDate(clockInDate);
                smartParkAttendanceRecord.setCreator(String.valueOf(smartParkAttendanceRecordQO.getUserId()));
                smartParkAttendanceRecord.beforeInsert();

                //存入打卡流水表
                SmartParkAttendanceRecordDetail smartParkAttendanceRecordDetail = new SmartParkAttendanceRecordDetail();
                BeanUtil.conversion(smartParkAttendanceRecord, smartParkAttendanceRecordDetail);
                smartParkAttendanceRecordDetail.beforeInsert();

                insert = smartParkAttendanceRecordDetailMapper.insert(smartParkAttendanceRecordDetail);

                if (recordStatus) {
                    SmartParkAttendanceRecordExample smartParkAttendanceRecordExample = new SmartParkAttendanceRecordExample();
                    smartParkAttendanceRecordExample.or().andUserIdEqualTo(smartParkAttendanceRecord.getUserId())
                            .andDeptIdEqualTo(smartParkAttendanceRecord.getDeptId())
                            .andCardShiftEqualTo(smartParkAttendanceRecord.getCardShift())
                            .andGroupIdEqualTo(smartParkAttendanceRecord.getGroupId())
                            .andShiftWorkTimeEqualTo(shiftWorkTime)
                            .andClockInDateEqualTo(clockInDate)
                            .andIsDeletedEqualTo(0);
                    List<SmartParkAttendanceRecord> smartParkAttendanceRecords = smartParkAttendanceRecordMapper.selectByExample(smartParkAttendanceRecordExample);
                    //查询当前人在当前班次打卡段是否打过卡
                    if (smartParkAttendanceRecords.size() > 0) {
                        smartParkAttendanceRecord = smartParkAttendanceRecords.get(0);
                        if (isSignIn) {
                            //如果是签到，当前时间在记录时间之前更新，之后不做操作
                            if (smartParkAttendanceRecordQO.getClockInTime().before(smartParkAttendanceRecord.getClockInTime())) {
                                smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                                smartParkAttendanceRecord.setClockInStatusName(clockInStatusName);
                                smartParkAttendanceRecord.setClockInTime(smartParkAttendanceRecordQO.getClockInTime());
                                insert = smartParkAttendanceRecordMapper.updateByPrimaryKey(smartParkAttendanceRecord);
                            }
                        } else {
                            //如果是签退，当前时间在记录时间之后更新，之前不做操作
                            if (smartParkAttendanceRecordQO.getClockInTime().after(smartParkAttendanceRecord.getClockInTime())) {
                                smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                                smartParkAttendanceRecord.setClockInStatusName(clockInStatusName);
                                smartParkAttendanceRecord.setClockInTime(smartParkAttendanceRecordQO.getClockInTime());
                                insert = smartParkAttendanceRecordMapper.updateByPrimaryKey(smartParkAttendanceRecord);
                            }
                        }
                    } else {
                        insert = smartParkAttendanceRecordMapper.insert(smartParkAttendanceRecord);
                    }
                }
            }
            return ResponseBodyWrapperUtil.toResData(insert);
        } catch (Exception e) {
            logger.error("", e);
            return ResponseBodyWrapperUtil.fail(ErrMsgEnum.ERROR_SYSTEM.getErrorMessage(), ErrMsgEnum.ERROR_SYSTEM.getErrorCode());
        }

    }


    /**
     * @param smartParkAttendanceRecordQO:
     * @Description: 保存异常打卡记录
     * @Author: ChenYong
     * @Date: 2021/8/3 0003
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody saveAbnormalAttendanceRecord(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {
        String format = "yyyy-MM-dd HH:mm:ss";
        String clockInDateFormat = "yyyy-MM-dd";
        Date date = new Date();
        if (smartParkAttendanceRecordQO.getClockInTime() != null) {
            date = smartParkAttendanceRecordQO.getClockInTime();
        }
        //打卡日期
        String clockInDate = "";
        if(StringUtils.isEmpty(smartParkAttendanceRecordQO.getClockInDate())){
            clockInDate = DateUtil.format(date, clockInDateFormat);
        }
        try {

            if (smartParkAttendanceRecordQO.getUserId() == null) {
                return ResponseBodyWrapperUtil.fail("用户ID不能为空", "80013");
            }
            if (smartParkAttendanceRecordQO.getTenantId() == null) {
                return ResponseBodyWrapperUtil.fail("租户ID不能为空", "80016");
            }


            List<SmartParkGroupWhiteList> smartParkGroupWhiteLists = new ArrayList<>();
            if (smartParkAttendanceRecordQO.getUserId() != null) {
                SmartParkGroupWhiteListExample smartParkGroupWhiteListExample = new SmartParkGroupWhiteListExample();
                smartParkGroupWhiteListExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                smartParkGroupWhiteLists = smartParkGroupWhiteListMapper.selectByExample(smartParkGroupWhiteListExample);
            }
            if (smartParkGroupWhiteLists.size() > 0) {
                return ResponseBodyWrapperUtil.fail("当前用户为考勤白名单", "80001");
            }

            //考勤对象，判断用户是否绑定考勤组
            List<SmartParkGroupObject> smartParkGroupObjects = new ArrayList<>();
            if (smartParkAttendanceRecordQO.getUserId() != null) {
                SmartParkGroupObjectExample smartParkGroupObjectExample = new SmartParkGroupObjectExample();
                smartParkGroupObjectExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                ;
                smartParkGroupObjects = smartParkGroupObjectMapper.selectByExample(smartParkGroupObjectExample);
            }
            if (smartParkGroupObjects.size() < 1) {
                return ResponseBodyWrapperUtil.fail("当前用户未绑定考勤组", "80001");
            }

            //考勤组信息
            SmartParkAttendanceGroup smartParkAttendanceGroup = smartParkAttendanceGroupMapper.selectByPrimaryKey(smartParkGroupObjects.get(0).getGroupId());
            if (smartParkAttendanceGroup == null) {
                return ResponseBodyWrapperUtil.fail("未获取到考勤组信息", "80002");
            }
            if (smartParkAttendanceGroup.getEnableStatus() == 0) {
                return ResponseBodyWrapperUtil.fail("考勤组未启用", "80010");
            }

            //判断当天是否为特殊日期
            SmartParkGroupSpecialDateExample smartParkGroupSpecialDateExample = new SmartParkGroupSpecialDateExample();
            Date handle = DateTimeUtil.handle(date, 00, 00);
            smartParkGroupSpecialDateExample.or().andSpecialDateEqualTo(handle)
                    .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                    .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                    .andIsDeletedEqualTo(0);
            List<SmartParkGroupSpecialDate> smartParkGroupSpecialDates = smartParkGroupSpecialDateMapper.selectByExample(smartParkGroupSpecialDateExample);

            Long shiftId = null;
            //是否需要打卡
            boolean status;
            //打卡时间的工作日
            int weekDay = 0;
            if (smartParkGroupSpecialDates.size() > 0) {
                //当前日期为特殊日期
                //如果是判断是否需要上班
                if (smartParkGroupSpecialDates.get(0).getShiftId() != 0) {
                    shiftId = smartParkGroupSpecialDates.get(0).getShiftId();
                    //需要打卡
                    status = true;
                } else {
                    return ResponseBodyWrapperUtil.fail("当前日期为休息日", "80004");
                }
            } else {
                //当前日期不是特殊日期
                //获取节假日信息
                String times = DateUtil.format(date, format);
                SmartParkHolidayDetailQO smartParkHolidayDetailQO = new SmartParkHolidayDetailQO();
                smartParkHolidayDetailQO.setTimes(times);
                smartParkHolidayDetailQO.setTenantId(smartParkAttendanceRecordQO.getTenantId());
                CommonResponseBody commonResponseBody = smartParkHolidayDetailService.queryByDate(smartParkHolidayDetailQO);
                //判断是否需要打卡
                if (commonResponseBody.getData()!=null && (Boolean)commonResponseBody.getData()) {
                    //需要打卡
                    //获取工作日班次信息
                    weekDay = DateTimeUtil.getWeekDay(date);
                    SmartParkGroupWeekdaysExample smartParkGroupWeekdaysExample = new SmartParkGroupWeekdaysExample();
                    smartParkGroupWeekdaysExample.or().andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                            .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                            .andWeekDayNumEqualTo(weekDay)
                            .andIsDeletedEqualTo(0);
                    List<SmartParkGroupWeekdays> smartParkGroupWeekdays = smartParkGroupWeekdaysMapper.selectByExample(smartParkGroupWeekdaysExample);
                    if (smartParkGroupWeekdays.size() < 1) {
                        return ResponseBodyWrapperUtil.fail("为获取到对应的工作日信息", "80005");
                    }
                    shiftId = smartParkGroupWeekdays.get(0).getShiftId();
                    status = true;
                } else {
                    return ResponseBodyWrapperUtil.fail("当前日期为休息日", "80004");
                }
            }

            //转换实体
            SmartParkAttendanceRecord smartParkAttendanceRecord = new SmartParkAttendanceRecord();

            //需要打卡获取班次打卡时间段
            if (status) {
                SmartParkShift smartParkShift;
                if (shiftId != null && shiftId != 0) {
                    smartParkShift = smartParkShiftMapper.selectByPrimaryKey(shiftId);
                    if (smartParkShift == null) {
                        return ResponseBodyWrapperUtil.fail("未获取到班次信息", "80007");
                    }
                    if (smartParkShift.getEnableStatus() == 0) {
                        return ResponseBodyWrapperUtil.fail("当前班次未启用", "80009");
                    }
                } else {
                    return ResponseBodyWrapperUtil.fail("当前日期为休息日或班次ID为空", "80008");
                }

                //考勤状态
                Integer clockInStatus = 5;
                //考勤状态名
                String clockInStatusName = "缺卡";

                //获取班次所有打卡时间段，判断是在哪一个时间段内
                SmartParkShiftDetailsExample smartParkShiftDetailsExample = new SmartParkShiftDetailsExample();
                smartParkShiftDetailsExample.or().andShiftIdEqualTo(shiftId)
                        .andTenantIdEqualTo(smartParkAttendanceRecordQO.getTenantId())
                        .andIsDeletedEqualTo(0);
                ;
                List<SmartParkShiftDetails> smartParkShiftDetailsList = smartParkShiftDetailsMapper.selectByExample(smartParkShiftDetailsExample);
                for (SmartParkShiftDetails smartParkShiftDetails : smartParkShiftDetailsList) {
                    //开始根据班次详情查询是否请假或出差，查询是否以及打过卡
                    //处理班次详情的签到时间
                    String[] signInTimes = smartParkShiftDetails.getSignInTime().split(":");
                    String signInHour = signInTimes[0];
                    String signInMinute = signInTimes[1];
                    Date handleSignInTime = DateTimeUtil.handle(date, Integer.valueOf(signInHour), Integer.valueOf(signInMinute));

                    //处理班次详情的签退时间
                    String[] signOutTimes = smartParkShiftDetails.getSignOutTime().split(":");
                    String signOutHour = signOutTimes[0];
                    String signOutMinute = signOutTimes[1];
                    Date handleSignOutTime = DateTimeUtil.handle(date, Integer.valueOf(signOutHour), Integer.valueOf(signOutMinute));


                    //赋值存入考勤记录
                    smartParkAttendanceRecord.setUserName(smartParkAttendanceRecordQO.getUserName());
                    smartParkAttendanceRecord.setDeptId(smartParkAttendanceRecordQO.getDeptId());
                    smartParkAttendanceRecord.setDeptName(smartParkAttendanceRecordQO.getDeptName());
                    smartParkAttendanceRecord.setUserId(smartParkAttendanceRecordQO.getUserId());

                    smartParkAttendanceRecord.setAbnormalMinutes(0);
                    smartParkAttendanceRecord.setCardShift(smartParkShift.getId());
                    smartParkAttendanceRecord.setCardShiftName(smartParkShift.getShiftName());
                    smartParkAttendanceRecord.setGroupId(smartParkAttendanceGroup.getId());
                    smartParkAttendanceRecord.setGroupName(smartParkAttendanceGroup.getAttendanceGroupName());
                    smartParkAttendanceRecord.setClockInWeek(weekDay);
                    smartParkAttendanceRecord.setDispose(0);
                    smartParkAttendanceRecord.setCardSupplement(0);
                    smartParkAttendanceRecord.setClockInDate(clockInDate);
                    smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                    smartParkAttendanceRecord.setClockInStatusName(clockInStatusName);
                    smartParkAttendanceRecord.setCreator(String.valueOf(smartParkAttendanceRecordQO.getUserId()));
                    smartParkAttendanceRecord.setClockInWay(9);
                    smartParkAttendanceRecord.setClockInWayName("系统生成");
                    smartParkAttendanceRecord.setTenantId(smartParkAttendanceRecordQO.getTenantId());
                    smartParkAttendanceRecord.beforeInsert();


                    //查询当天签到时间是否在假期或出差中
                    SmartParkAttendanceUserOccupy signInTimeUserOccupy = new SmartParkAttendanceUserOccupy();
                    signInTimeUserOccupy.setNowDate(handleSignInTime);
                    signInTimeUserOccupy.setUserId(smartParkAttendanceRecordQO.getUserId());
                    List<SmartParkAttendanceUserOccupy> signInTimeUserOccupyList = smartParkAttendanceUserOccupyMapper.selectByTime(signInTimeUserOccupy);
                    if (signInTimeUserOccupyList.size() > 0) {
                        //请假的记录生成
                        SmartParkAttendanceApprove smartParkAttendanceApprove = smartParkAttendanceApproveMapper.selectByPrimaryKey(signInTimeUserOccupyList.get(0).getBusinessId());
                        if(smartParkAttendanceApprove!=null){
                            SmartParkVacationType smartParkVacationType = smartParkVacationTypeMapper.selectByPrimaryKey(Long.valueOf(smartParkAttendanceApprove.getLeaveType()));
                            if(smartParkAttendanceApprove.getApproveType() != 3){
                                smartParkAttendanceRecord.setClockInStatus(smartParkAttendanceApprove.getLeaveType());
                                smartParkAttendanceRecord.setClockInStatusName(smartParkVacationType.getVacationName());
                                smartParkAttendanceRecord.setSupplement(smartParkVacationType.getId());
                            }
                        }
                        smartParkAttendanceRecord.setShiftWorkTime(smartParkShiftDetails.getSignInTime());
                        smartParkAttendanceRecord.setClockInType(1);
                        smartParkAttendanceRecord.setClockInTypeName("签到");
                        smartParkAttendanceRecordMapper.insert(smartParkAttendanceRecord);
                        return ResponseBodyWrapperUtil.fail("当前用户" + signInTimeUserOccupyList.get(0).getBusinessType() + "中", "80021");
                    } else {
                        //根据签到时间查询考勤记录
                        SmartParkAttendanceRecordExample smartParkAttendanceRecordExample = new SmartParkAttendanceRecordExample();
                        smartParkAttendanceRecordExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                                .andCardShiftEqualTo(smartParkShift.getId())
                                .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                                .andShiftWorkTimeEqualTo(smartParkShiftDetails.getSignInTime())
                                .andClockInDateEqualTo(clockInDate)
                                .andIsDeletedEqualTo(0);
                        List<SmartParkAttendanceRecord> signInTimeAttendanceRecordList = smartParkAttendanceRecordMapper.selectByExample(smartParkAttendanceRecordExample);
                        if (signInTimeAttendanceRecordList.size() < 1) {
                            //不存在记录，保存缺卡记录
                            smartParkAttendanceRecord.setShiftWorkTime(smartParkShiftDetails.getSignInTime());
                            smartParkAttendanceRecord.setClockInType(1);
                            smartParkAttendanceRecord.setClockInTypeName("签到");
                            smartParkAttendanceRecordMapper.insert(smartParkAttendanceRecord);
                        } else {
                            System.out.print("当前打卡时间段已签到");
                        }
                    }


                    //查询当天签退时间是否在假期或出差中
                    SmartParkAttendanceUserOccupy signOutTimeUserOccupy = new SmartParkAttendanceUserOccupy();
                    signOutTimeUserOccupy.setNowDate(handleSignOutTime);
                    signOutTimeUserOccupy.setUserId(smartParkAttendanceRecordQO.getUserId());
                    List<SmartParkAttendanceUserOccupy> signOutTimeUserOccupyList = smartParkAttendanceUserOccupyMapper.selectByTime(signOutTimeUserOccupy);
                    if (signOutTimeUserOccupyList.size() > 0) {
                        //请假的记录生成
                        SmartParkAttendanceApprove smartParkAttendanceApprove = smartParkAttendanceApproveMapper.selectByPrimaryKey(signInTimeUserOccupyList.get(0).getBusinessId());
                        if(smartParkAttendanceApprove!=null){
                            SmartParkVacationType smartParkVacationType = smartParkVacationTypeMapper.selectByPrimaryKey(Long.valueOf(smartParkAttendanceApprove.getLeaveType()));
                            if(smartParkAttendanceApprove.getApproveType() != 3){
                                smartParkAttendanceRecord.setClockInStatus(smartParkAttendanceApprove.getLeaveType());
                                smartParkAttendanceRecord.setClockInStatusName(smartParkVacationType.getVacationName());
                                smartParkAttendanceRecord.setSupplement(smartParkVacationType.getId());
                            }
                        }
                        smartParkAttendanceRecord.setClockInDate(clockInDate);
                        smartParkAttendanceRecord.setClockInStatus(clockInStatus);
                        smartParkAttendanceRecord.setShiftWorkTime(smartParkShiftDetails.getSignOutTime());
                        smartParkAttendanceRecord.setClockInType(2);
                        smartParkAttendanceRecord.setClockInTypeName("签退");
                        smartParkAttendanceRecordMapper.insert(smartParkAttendanceRecord);
                        return ResponseBodyWrapperUtil.fail("当前用户" + signOutTimeUserOccupyList.get(0).getBusinessType() + "中", "80021");
                    } else {
                        //根据签退时间查询考勤记录
                        SmartParkAttendanceRecordExample smartParkAttendanceRecordExample = new SmartParkAttendanceRecordExample();
                        smartParkAttendanceRecordExample.or().andUserIdEqualTo(smartParkAttendanceRecordQO.getUserId())
                                .andCardShiftEqualTo(smartParkShift.getId())
                                .andGroupIdEqualTo(smartParkAttendanceGroup.getId())
                                .andShiftWorkTimeEqualTo(smartParkShiftDetails.getSignOutTime())
                                .andClockInDateEqualTo(clockInDate)
                                .andIsDeletedEqualTo(0);
                        List<SmartParkAttendanceRecord> signOutTimeAttendanceRecordList = smartParkAttendanceRecordMapper.selectByExample(smartParkAttendanceRecordExample);
                        if (signOutTimeAttendanceRecordList.size() < 1) {
                            //不存在记录，保存缺卡记录
                            smartParkAttendanceRecord.setShiftWorkTime(smartParkShiftDetails.getSignOutTime());
                            smartParkAttendanceRecord.setClockInType(2);
                            smartParkAttendanceRecord.setClockInTypeName("签退");
                            smartParkAttendanceRecordMapper.insert(smartParkAttendanceRecord);
                        } else {
                            System.out.print("当前打卡时间段已签退");
                        }
                    }
                }
            }
            return ResponseBodyWrapperUtil.fail("缺卡记录生成完成", "80099");
        } catch (Exception e) {
            logger.error("", e);
            return ResponseBodyWrapperUtil.fail(ErrMsgEnum.ERROR_SYSTEM.getErrorMessage(), ErrMsgEnum.ERROR_SYSTEM.getErrorCode());
        }

    }

    /**
     * 手动异常打卡记录
     * @Description:  手动异常打卡记录
     * @Author: ChenYong
     * @Date: 2021/8/31 0031
     * @param smartParkAttendanceRecordQO:
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody manualSaveAbnormalRecord(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {
        SmartParkGroupObjectExample smartParkGroupObjectExample = new SmartParkGroupObjectExample();
        smartParkGroupObjectExample.or().andIsDeletedEqualTo(0);
        List<SmartParkGroupObject> smartParkGroupObjects = smartParkGroupObjectMapper.selectByExample(smartParkGroupObjectExample);
        List<Date> dateList = DateTimeUtil.findDates(smartParkAttendanceRecordQO.getStartTime(),smartParkAttendanceRecordQO.getEndTime());
        for (Date date:dateList){
            for (SmartParkGroupObject smartParkGroupObject:smartParkGroupObjects){
                SmartParkAttendanceRecordQO smartParkAttendanceRecord = new SmartParkAttendanceRecordQO();
                SsoUserRpcQO qo = new SsoUserRpcQO();
                qo.setUserId(String.valueOf(smartParkGroupObject.getUserId()));
                CommonResponseBody<SsoUserRpcQO> userDetail = aclUserRpcService.getUserDetail(qo);
                if(userDetail.getData()!=null&&userDetail.getData().getDeptList().size()>0){
                    smartParkAttendanceRecord.setDeptId(userDetail.getData().getDeptList().get(0).getId());
                    smartParkAttendanceRecord.setDeptName(userDetail.getData().getDeptList().get(0).getDeptName());
                    smartParkAttendanceRecord.setUserName(userDetail.getData().getNickName());
                }
                smartParkAttendanceRecord.setClockInTime(date);
                smartParkAttendanceRecord.setUserId(smartParkGroupObject.getUserId());
                smartParkAttendanceRecord.setTenantId(smartParkGroupObject.getTenantId());
                saveAbnormalAttendanceRecord(smartParkAttendanceRecord);
            }
        }
        return ResponseBodyWrapperUtil.fail("缺卡记录生成完成", "80099");
    }

    /**
     * 手动保存打卡记录
     * @Description:  手动保存打卡记录
     * @Author: ChenYong
     * @Date: 2021/8/31 0031
     * @param smartParkAccessControlPassRecordQO:
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody manualSaveRecord(SmartParkAccessControlPassRecordQO smartParkAccessControlPassRecordQO) {
        SmartParkAccessControlPassRecordExampleExt recordExample = new SmartParkAccessControlPassRecordExampleExt();
        SmartParkAccessControlPassRecordExampleExt.Criteria criteria = recordExample.createCriteria();
        if(smartParkAccessControlPassRecordQO.getPassStartTime() == null && smartParkAccessControlPassRecordQO.getPassEndTime() == null){
            return ResponseBodyWrapperUtil.fail("请输入开始时间和结束时间", "80099");
        }
        criteria.andPassTimeBetween(smartParkAccessControlPassRecordQO.getPassStartTime(),smartParkAccessControlPassRecordQO.getPassEndTime()).andPassPersonTypeEqualTo("1");
        List<SmartParkAccessControlPassRecord> smartParkAccessControlPassRecords = smartParkAccessControlPassRecordMapper.selectByExample(recordExample);
        for (SmartParkAccessControlPassRecord smartParkAccessControlPassRecord : smartParkAccessControlPassRecords){
            SmartParkAttendanceRecordQO smartParkAttendanceRecordQO = new SmartParkAttendanceRecordQO();
            smartParkAttendanceRecordQO.setTenantId(smartParkAccessControlPassRecord.getTenantId());

            smartParkAttendanceRecordQO.setUserId(Long.valueOf(smartParkAccessControlPassRecord.getCreator()));
            smartParkAttendanceRecordQO.setUserName(smartParkAccessControlPassRecord.getPassPersonName());
            SsoUserRpcQO qo = new SsoUserRpcQO();
            qo.setUserId(smartParkAccessControlPassRecord.getCreator());
            CommonResponseBody<SsoUserRpcQO> userDetail = aclUserRpcService.getUserDetail(qo);
            if(userDetail.getData()!=null&&userDetail.getData().getDeptList().size()>0){
                smartParkAttendanceRecordQO.setDeptId(userDetail.getData().getDeptList().get(0).getId());
                smartParkAttendanceRecordQO.setDeptName(userDetail.getData().getDeptList().get(0).getDeptName());
            }
            /*smartParkAttendanceRecordQO.setDeptId(111L);
            smartParkAttendanceRecordQO.setDeptName("测试");*/
            smartParkAttendanceRecordQO.setClockInTime(smartParkAccessControlPassRecord.getPassTime());
            smartParkAttendanceRecordQO.setClockInSource(Long.valueOf(smartParkAccessControlPassRecord.getDeviceCode()));
            smartParkAttendanceRecordQO.setClockInSourceName(smartParkAccessControlPassRecord.getDeviceName());
            smartParkAttendanceRecordQO.setClockInWay(1);
            smartParkAttendanceRecordQO.setClockInWayName("门禁打卡");

            CommonResponseBody commonResponseBody = saveAttendanceRecord(smartParkAttendanceRecordQO);
        }
        return ResponseBodyWrapperUtil.fail("手动生成考勤记录完成", "80099");
    }


    /**
     * @param smartParkAttendanceRecordQO:
     * @Description: 修改打卡记录
     * @Author: ChenYong
     * @Date: 2021/8/3 0003
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody updateAttendanceRecord(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {
        return null;
    }

    /**
     * @param smartParkAttendanceRecordQO:
     * @Description: 删除打卡记录
     * @Author: ChenYong
     * @Date: 2021/8/3 0003
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody deleteAttendanceRecord(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {
        return null;
    }

    /**
     * @param smartParkAttendanceRecordQO:
     * @Description: 打卡记录详情
     * @Author: ChenYong
     * @Date: 2021/8/3 0003
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody attendanceRecordDetails(SmartParkAttendanceRecordQO smartParkAttendanceRecordQO) {
        return null;
    }
}
